using System;
using System.Collections.Generic;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
using Microsoft.SmallBasic.Library;
using Math=System.Math;

namespace SmallBasicFun
{
	/// <summary>
	/// Big Shapes, Small Shapes, Circles, Squares
	/// from tiny Triangles to dazzling Diamonds
	/// You want them, we've got them! Don't settle for 
	/// boring shapeless programs, add some of our 
	/// spectacular shapes to your programs today!
	/// </summary>
	[SmallBasicType]
	public class ShapeMaker
	{
		static ShapeMaker()
		{
			ProgramWindow.Show();

		}
		public static readonly ShapeMakerTasks shapes = new ShapeMakerTasks();

		/// <summary>
		/// Creates a circle that you can place on the ProgramWindow
		/// </summary>
		/// <example> circle = ShapeMaker.CreateCircle(20)</example>
		/// <param name="radiusInPixels"> The radius of the circle in pixels</param>
		/// <returns>The Shape you've just created</returns>
		public static Primitive CreateCircle(Primitive radiusInPixels)
		{
			string name = shapes.CreateName();
			GraphicsWindow.Show();
			GraphicsWindowHelper.Invoke(() => { shapes.CreateCircle(name, radiusInPixels); });
			return name;
		}
		/// <summary>
		/// Creates a rectangle that you can place on the ProgramWindow
		/// </summary>
		/// <example> box = ShapeMaker.CreateRectangle(30,40)</example>
		/// <param name="width"> The width of the rectangle in pixels</param>
		/// <param name="height"> The height of the rectangle in pixels</param>
		/// <returns>The Shape you've just created</returns>
		public static Primitive CreateRectangle(Primitive width, Primitive height)
		{
			string name = shapes.CreateName();
			GraphicsWindow.Show();
			GraphicsWindowHelper.Invoke(() => { shapes.CreateRectangle(name, width, height); });
			return name;
		}

		/// <summary>
		/// Restores the default colors and thickness
		/// </summary>
		/// <example>
		/// ShapeMaker.RestoreDefaults()
		/// </example>
		public static void RestoreDefaults()
		{
			shapes.RestoreDefaults();
		}


		/// <summary>
		/// Changes the levels of opacity on a shape.
		/// 100% Opacity is a completely solid shape.
		/// 0% Opacity is a completely transparent shape. 
		/// </summary>
		/// <example>ShapeMaker.SetOpacity(ShapeMaker.CreateCircle(20), 42)</example>
		/// <param name="shape">The shape you want to alter</param>
		/// <param name="percentOpaque">The percentage of opacity desired (0-100)</param>
		public static void SetOpacity(Primitive shape, Primitive percentOpaque)
		{
			GraphicsWindowHelper.Invoke(() => { shapes.SetOpacity(shape, percentOpaque); });
		}

		/// <summary>
		/// Sets the Color for the inside of the next shape you create.
		/// </summary>
		/// <example>ShapeMaker.SetColorForNextShape("green")</example>
		/// <param name="color">The Color of the next shape</param>
		public static void SetColorForNextShape(Primitive color)
		{
			shapes.SetColorForNextShape(GraphicsWindowHelper.GetColorFromString(color));
		}

		/// <summary>
		/// Sets the Color for the outside line of the next shape you create.
		/// </summary>
		/// <example>ShapeMaker.SetOutlineColorForNextShape("purple")</example>
		/// <param name="color">The Color of outline of the next shape</param>
		public static void SetOutlineColorForNextShape(Primitive color)
		{
			shapes.SetOutlineColorForNextShape(GraphicsWindowHelper.GetColorFromString(color));
		}

		/// <summary>
		/// Removes a shape from the Program Window
		/// </summary>
		/// <example>ShapeMaker.RemoveShape(circle)</example>
		/// <param name="shape">The shape you want to remove</param>
		public static void RemoveShape(Primitive shape)
		{
			GraphicsWindowHelper.Invoke(() => { shapes.RemoveShape(shape); });
		}

		/// <summary>
		/// Centers a shape at a given location
		/// </summary>
		/// <example>ShapeMaker.CenterShapeAt(ShapeMaker.CreateCircle(20), 20, 20)</example>
		/// <param name="shape">The shape you want centered</param>
		/// <param name="x">The X coordinate of the center</param>
		/// <param name="y">The Y coordinate of the center</param>
		public static void CenterShapeAt(Primitive shape, Primitive x, Primitive y)
		{
			GraphicsWindowHelper.Invoke(() =>
			{
				shapes.CenterShapeAt(shape, x, y);
			});
		}

		
	}

	public class ShapeMakerTasks
	{
		private readonly Dictionary<string, Shape> shapes = new Dictionary<string, Shape>();
		private Color fill = System.Windows.Media.Colors.Beige;
		private Color outline = System.Windows.Media.Colors.Black;
		private int ShapeCount;
		private double thickness = 2;

		public Shape GetShape(String primitive)
		{
			return shapes.ContainsKey(primitive) ? shapes[primitive] : null;
		}

		public void CreateCircle(string name, double radius)
		{
			var ellipse = new Ellipse
			              	{
			              		StrokeThickness = thickness,
			              		Fill = new SolidColorBrush(fill),
			              		Height = radius*2,
			              		Width = radius*2,
			              		Name = name,
			              		Stroke = new SolidColorBrush(outline)
			              	};
			shapes[name] = ellipse;
			Move(ellipse, -ellipse.Height - 1, -ellipse.Height - 1);
			GraphicsWindowHelper.GetCanvas().Children.Add(ellipse);
		}
public void CreateRectangle(string name, double width, double height)
		{
			var rectangle = new Rectangle()
			              	{
			              		StrokeThickness = thickness,
			              		Fill = new SolidColorBrush(fill),
			              		Height = height,
			              		Width = width,
			              		Name = name,
			              		Stroke = new SolidColorBrush(outline)
			              	};
			shapes[name] = rectangle;
			Move(rectangle, -rectangle.Height - 1, -rectangle.Height - 1);
			GraphicsWindowHelper.GetCanvas().Children.Add(rectangle);
		}

		public string CreateName()
		{
			return "Shape" + ShapeCount++;
		}

		public static void Move(Shape ellipse, double xLeft, double yTop)
		{
			Canvas.SetTop(ellipse, yTop);
			Canvas.SetLeft(ellipse, xLeft);
		}

		public void SetOpacity(Primitive shape, double percentOpaque)
		{
			Shape s = GetShape(shape);
			if (s != null)
			{
				s.Opacity = Math.Min(100, Math.Max(0, percentOpaque))/100.0;
			}
		}

		public void RestoreDefaults()
		{
			outline = System.Windows.Media.Colors.Black;
			fill = System.Windows.Media.Colors.Beige;
			thickness = 2;
		}

		public void SetColorForNextShape(Color color)
		{
			fill = color;
		}

		public void SetOutlineColorForNextShape(Color color)
		{
			outline = color;
		}

		public void RemoveShape(Primitive shape)
		{
			Shape s = GetShape(shape);
			if (s != null)
			{
				GraphicsWindowHelper.GetCanvas().Children.Remove(s);
			}
		}

		public void CenterShapeAt(Primitive shape, double x, double y)
		{
			var shapeObject = GetShape(shape);
			if (shapeObject == null)
			{
				return;
			}
			var xCenter = x - shapeObject.Width / 2;
			var yCenter = y - shapeObject.Height / 2;
			Move(shapeObject, xCenter, yCenter);
		}
	}
}